#include "gpiocontrol.h"

GPIOControl::GPIOControl() {
}

qint16 GPIOControl::exp(qint16 gpio) {
  qint16 fd, len;
  char buf[MAX_BUF];

  fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with export";
    return fd;
  }

  len = snprintf(buf, sizeof(buf), "%d", gpio);
  write(fd, buf, len);
  close(fd);

  return 0;
}

qint16 GPIOControl::unexp(qint16 gpio) {
  qint16 fd, len;
  char buf[MAX_BUF];

  fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with unexport";
    return fd;
  }

  len = snprintf(buf, sizeof(buf), "%d", gpio);
  write(fd, buf, len);
  close(fd);
  return 0;
}

qint16 GPIOControl::setDirection(qint16 gpio, PIN_DIRECTION outFlag)
{
  qint16 fd;
  char buf[MAX_BUF];

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);

  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with GPIO set direction";
    return fd;
  }

  if (outFlag == OUTPUT_PIN)
    write(fd, "out", 4);
  else
    write(fd, "in", 3);

  close(fd);
  return 0;
}

qint16 GPIOControl::setValue(qint16 gpio, PIN_VALUE value)
{
  qint16 fd;
  char buf[MAX_BUF];

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with GPIO set value";
    return fd;
  }

  if (value==LOW)
    write(fd, "0", 2);
  else
    write(fd, "1", 2);

  close(fd);
  return 0;
}

qint16 GPIOControl::getValue(qint16 gpio, qint16 *value)
{
  qint16 fd;
  char buf[MAX_BUF];
  char ch;

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_RDONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with GPIO get value";
    return fd;
  }

  read(fd, &ch, 1);

  if (ch != '0') {
    *value = 1;
  } else {
    *value = 0;
  }

  close(fd);
  return 0;
}

qint16 GPIOControl::setEdge(qint16 gpio, char *edge)
{
  qint16 fd;
  char buf[MAX_BUF];

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);

  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    qDebug() << "GPIO: Error with GPIO/set-edge";
    return fd;
  }

  write(fd, edge, strlen(edge) + 1);
  close(fd);
  return 0;
}

qint16 GPIOControl::fdOpen(qint16 gpio) {
  qint16 fd;
  char buf[MAX_BUF];

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

  fd = open(buf, O_RDONLY | O_NONBLOCK );
  if (fd < 0) {
    qDebug() << "GPIO: Error with gpio/fd_open";
  }

  return fd;
}

qint16 GPIOControl::fdClose(qint16 fd) {
  return close(fd);
}
